from datetime import datetime
import time
import os
import pandas as pd
from pathlib import Path

# 时间戳 转日期时间
def timeToDate(ts,isShiqu=True):
    if(len(ts)==13):
        timestamp_s = int(ts) / 1000
    else: 
        timestamp_s = int(ts)
    if isShiqu:
        dt_object = datetime.fromtimestamp(timestamp_s) #+8*3600
    else:
        dt_object = datetime.fromtimestamp(timestamp_s)
    formatted_date = dt_object.strftime('%Y-%m-%d %H:%M:%S')
    return formatted_date


# 日期时间 转时间戳
def dateToTime(date):
    dt_obj = datetime.strptime(date, "%Y-%m-%d %H:%M:%S")
    timestamp = int(dt_obj.timestamp() * 1000)
    return timestamp

# 自动获取根目录
def get_project_root():
    """自动获取项目根目录（通过向上查找包含特定标记文件的目录）"""
    # 方法1：查找包含 .git/ 或 requirements.txt 的目录作为根目录
    current = Path(__file__).absolute()
    while not any((current / marker).exists() for marker in ['.git', 'requirements.txt', 'project_root']):
        if current.parent == current:
            # 已经到达文件系统根目录
            return Path.cwd()  # 回退到当前工作目录
        current = current.parent
    return current

# 传入币种 返回对应的文件名
def getFilename(instId,bar="15m"):
    project_root = get_project_root()
    data_root =project_root/ "trading_data"
    data_root.mkdir(exist_ok=True)  # 确保目录存在
    filename = data_root / f"{instId}_{bar}.csv"
    return filename


# 获取 某个时间 距离现在过去了多久
def getHoursPassed(time_str):
    target_time = time_str  # 解析字符串
    current_time = datetime.now()

    hours_passed = (current_time - target_time).total_seconds() / 3600
    return round(hours_passed,2)


# 计算信号的短期胜率
# 传递带信号的 df  以及指定信号字段  -1 代表做空  1 代表做多
def getShenglv(df,field_signal='signal'):
    
    # 未来10根k线的收盘价
    df['future_close_10'] = df['close'].shift(-10)
    # 计算10日后的涨跌幅（百分比）
    df['diezhang_10'] = (df['future_close_10'] - df['close']) / df['close'] * 100
    df['future_close_5'] = df['close'].shift(-5)
    # 计算10日后的涨跌幅（百分比）
    df['diezhang_5'] = (df['future_close_5'] - df['close']) / df['close'] * 100

    # 获取所有信号数据
    df_signal = df[df[field_signal]!=0]

    count = len(df_signal)
    zheng5 = ((df_signal[field_signal]==1 ) & (df_signal['diezhang_5']>0)  ).sum() +  ((df_signal[field_signal]==-1 ) & (df_signal['diezhang_5']<0)  ).sum()
    zheng10 = ((df_signal[field_signal]==1 ) & (df_signal['diezhang_10']>0)  ).sum() +  ((df_signal[field_signal]==-1 ) & (df_signal['diezhang_10']<0)  ).sum()
    return round(zheng5/count*100,2),round(zheng10/count*100,2)

def getShenglvShow(df,instId,field_signal='signal',limit=20):
    df_signal = df[df[field_signal]!=0]
    shenglv5,shenglv10 = getShenglv(df)
    
    df_signal = df_signal[['open','close','signal','diezhang_5','diezhang_10']]
    # print(df_signal.tail(limit))
    print(f"{instId}信号数量：{len(df_signal)} 5日胜率：{shenglv5}%  10日胜率：{shenglv10}%")

# 防止数据不完整时调用脚本
def should_skip():
    now = datetime.now()
    # 检查当前分钟数是否在 0-4 之间（即每小时的前5分钟）
    return now.minute < 5

# 智能读取数据
def loadCsvData(instId,cycle = '15m',limit=0):
    # 读取加载数据
    # instId  要读取的币种
    # cycle   要读取的窗口周期
    # limit   要读取的记录条数（由新到旧）  0 为返回全部
    filePath = getFilename(instId + '-USDT-SWAP')
    if not os.path.exists(filePath):
        raise FileNotFoundError(f"文件路径不存在: {filePath}")
    
    # 读取 CSV 文件，不预先设置索引
    df = pd.read_csv(filePath)
    if len(df)==0:
        raise FileNotFoundError(f"{instId}未能读取到数据")
    # 转换时间戳 (毫秒 -> datetime)
    df['timestamp'] = pd.to_datetime(df['timestamp']+8*3600*1000, unit='ms')
    
    # 将时间戳设置为索引
    df.set_index('timestamp', inplace=True)
    if cycle!='15m':
                # 统一将周期转换为 Pandas 支持的 resample 规则
        resample_rule = {
            '1h': '1h',    # 1小时
            '4h': '4h',     # 4小时
            '1d': '1D',     # 1天（自然日）
            # '1w': '1W',     # 1周
            # '1m': '1M'      # 1月
        }.get(cycle.lower(), cycle)  # 默认直接使用输入的 cycle
        # 周期不一致 则聚合周期
                # 转换为指定的时间级别
        # 使用 resample 进行聚合
        df_resampled = df.resample(resample_rule).agg({
            'open': 'first',
            'high': 'max',
            'low': 'min',
            'close': 'last',
            'volume': 'sum'
        })
               # 检查是否需要丢弃未完成的 K 线
        if cycle.endswith(('h', 'd', 'w', 'm')):  # 如果是小时/天/周/月级别
            now = pd.Timestamp.now(tz=df.index.tz) if df.index.tz else pd.Timestamp.now()
            last_kline_time = df_resampled.index[-1]

            # 计算当前周期是否应该结束
            if cycle == '1d':
                # 对于自然日，判断今天是否已经走完
                today_start = pd.Timestamp(now.date())  # 今天的 00:00:00
                is_incomplete = (last_kline_time == today_start) and (now < today_start + pd.Timedelta(days=1))
            elif cycle == '4h':
                # 对于4小时，判断当前是否在最后一个4小时周期内
                next_kline_time = last_kline_time + pd.Timedelta(hours=4)
                is_incomplete = now < next_kline_time
            # ...（其他周期类似）...
            elif cycle == '1h':
                next_kline_time = last_kline_time + pd.Timedelta(hours=1)
                is_incomplete = now < next_kline_time


            if is_incomplete:
                df = df_resampled.iloc[:-1]  # 丢弃未完成的 K 线
            else:
                df = df_resampled
    if limit == 0:
        return df
    else:
        return df.tail(limit)